﻿using System;
using System.IO;
using System.Runtime.Serialization;
using System.Text;
using System.Xml;
using Catchbase.TestTools;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Moq;

namespace Catchbase.Service.API.UTest
{
    [TestClass]
    public class JsonHelperTest : TestBase<JsonHelper>
    {
        private Mock<IStreamProvider> _provider;
        private Testclass _testclass;
        private string _testclassAsJson;
        private TestableStream _stream;

        protected override void InitializeTest()
        {
            _testclass = new Testclass { Test = "some text øy" };
            _testclassAsJson = "{\"Test\":\"some text øy\"}";
            _stream = new TestableStream { ToRead = _testclassAsJson };
            _provider = new Mock<IStreamProvider>();
            _provider.Setup(r => r.GetStream()).Returns(_stream);
        }

        [TestMethod]
        public void WriteMustWriteJsonSerializedBytes()
        {
            Subject.Write(_provider.Object, _testclass);
            _stream.Written.MustStartWith(_testclassAsJson);
        }

        [TestMethod]
        public void WriteMustClose()
        {
            Subject.Write(_provider.Object, _testclass);
            _provider.Verify(p => p.ReleaseStream(_stream), Times.Once());
        }

        [TestMethod]
        public void ReadMustDeserializeFromJsonBytes()
        {
            Subject.Read<Testclass>(_provider.Object).Test.MustEqual(_testclass.Test);
        }

        [TestMethod]
        public void ReadMustClose()
        {
            Subject.Read<Testclass>(_provider.Object);
            _provider.Verify(p => p.ReleaseStream(_stream), Times.Once());
        }
    }

    [DataContract]
    public class Testclass
    {
        [DataMember]
        public string Test { get; set; }
    }

    public class TestableStream : Stream
    {
        public string Written { get; set; }
        public bool IsRead { get; set; }
        public string ToRead { get; set; }

        public override bool CanRead
        {
            get { return true; }
        }

        public override bool CanSeek
        {
            get { return false; }
        }


        public override bool CanWrite
        {
            get { return true; }
        }

        public override long Length
        {
            get { throw new NotImplementedException(); }
        }

        public override long Position
        {
            get { throw new NotImplementedException(); }
            set { throw new NotImplementedException(); }
        }

        public override void Flush()
        {
        }

        public override long Seek(long offset, SeekOrigin origin)
        {
            throw new NotImplementedException();
        }

        public override void SetLength(long value)
        {
            throw new NotImplementedException();
        }

        public override int Read(byte[] buffer, int offset, int count)
        {
            if (IsRead) return 0;
            IsRead = true;
            return FillBuffer(buffer);
        }

        public override void Write(byte[] buffer, int offset, int count)
        {
            Written = Encoding.UTF8.GetString(buffer);
        }

        public override void Close()
        {

        }

        private int FillBuffer(byte[] buffer)
        {
            byte[] bytes = Encoding.UTF8.GetBytes(ToRead);
            for (int i = 0; i < bytes.Length; i++)
            {
                buffer[i] = bytes[i];
            }
            return bytes.Length;
        }
    }
}